package ffte.core.mixed

import spinal.core._
import spinal.lib._

import ffte.types.VecComplex
import ffte.property.{getFFTIW,getFFTOW}
import ffte.algorithm.FFTGen.{psbFFT}

/**
 * Mixed Prime-Space Block (PSB) FFT implementation
 *
 * This class implements FFT using the Prime-Space Block decomposition method
 * with mixed architecture (combining flat and streamed implementations).
 * The mixed approach applies the most appropriate implementation style
 * to each stage of the PSB decomposition for optimal resource usage.
 *
 * Mixed PSB Architecture:
 * - First stage: Uses flat or streamed implementation based on rgen flag
 * - Second stage: Uses opposite architecture from first stage
 * - Chinese Remainder Theorem-based decomposition for coprime factors
 * - No twiddle factors required due to coprime decomposition
 *
 * Implementation Details:
 * - Direct streaming connection between stages (no twiddle multiplication)
 * - Data flows from first stage output to second stage input
 * - Mixed architecture selection handled by mixedComponents trait
 * - Simple pipelined connection for optimal throughput
 *
 * @tparam T Mixed method type parameter
 * @param S Scaling shift amount for fixed-point overflow prevention
 * @param p PSB decomposition structure containing stage information
 */
class psb[T <: Mixed](val S: Int, val p: psbFFT[T]) extends mixedComponents[T] {

    /**
     * Direct connection between first and second stages
     *
     * In PSB decomposition, no twiddle factors are required due to the
     * Chinese Remainder Theorem properties. The first stage output
     * connects directly to the second stage input.
     */
    f_block.u.io.q >> s_block.u.io.d

    /**
     * Input connection to first stage
     *
     * Routes the streaming input to the first stage FFT processor.
     * The first stage architecture (flat vs streamed) is determined
     * by the rgen flag in the mixedComponents trait.
     */
    io.d >> f_block.u.io.d

    /**
     * Output connection from second stage
     *
     * Routes the second stage output to the component output.
     * The second stage uses the opposite architecture from
     * the first stage for balanced performance.
     */
    io.q << s_block.u.io.q

    /**
     * Total component delay in clock cycles
     *
     * The total delay is the sum of delays through both stages
     * since they operate sequentially in the data flow path.
     *
     * @return Total delay from input to output in clock cycles
     */
    def delay = f_block.delay + s_block.delay
}
